orders.js ➔ getAllOrders   C
last analyzed

Complexity

Conditions 9

Size

Total Lines 49
Code Lines 32

Duplication

Lines 25
Ratio 51.02 %

Code Coverage

Tests 12
CRAP Score 9.2363

Importance

Changes 0
Metric Value
eloc 32
dl 25
loc 49
ccs 12
cts 14
cp 0.8571
rs 6.6666
c 0
b 0
f 0
cc 9
crap 9.2363
1 1
const db = require("../db/database.js");
2
3 1
module.exports = (function () {
4 1
    const dataFields = "orderId as id, customerName as name," +
5
        " customerAddress as address," +
6
        " customerZip as zip, customerCity as city," +
7
        " customerCountry as country, s.status, s.id as status_id";
8
9 1
    const orderItemsDataFields = "oi.productId as product_id, oi.amount," +
10
        " p.articleNumber as article_number, p.productName as name," +
11
        " p.productDescription as description, p.productSpecifiers as specifiers," +
12
        " p.stock, p.location, (p.price/100) as price";
13
14
    function getAllOrders(res, apiKey, status=200) {
15 4
        let orders = { data: []};
16
17 4
        db.all("SELECT " + dataFields +
18
            " FROM orders o INNER JOIN status s ON s.id = o.statusId" +
19
            " WHERE o.apiKey = ?",
20
        apiKey, (err, orderRows) => {
21 4
            if (err) {
22
                return res.status(500).json({
23
                    errors: {
24
                        status: 500,
25
                        source: "/orders",
26
                        title: "Database error",
27
                        detail: err.message
28
                    }
29
                });
30
            }
31
32 4
            if (orderRows.length === 0) {
33 2
                return res.status(status).json(orders);
34
            }
35
36 2 View Code Duplication
            orderRows.forEach(function(order) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
37 5
                db.all("SELECT " + orderItemsDataFields + " FROM order_items oi " +
38
                    "INNER JOIN products p ON oi.productId=p.productId AND oi.apiKey=p.apiKey" +
39
                    " WHERE oi.apiKey = ? AND oi.orderId = ?",
40
                apiKey,
41
                order.id, (err, orderItemRows) => {
42 5
                    if (err) {
43
                        return res.status(500).json({
44
                            errors: {
45
                                status: 500,
46
                                source: "/orders order_items",
47
                                title: "Database error",
48
                                detail: err.message
49
                            }
50
                        });
51
                    }
52
53 5
                    order.order_items = orderItemRows;
54 5
                    orders.data.push(order);
55
56 5
                    if (orders.data.length === orderRows.length) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if orders.data.length === orderRows.length is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
57 2
                        res.status(status).json(orders);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
58
                    }
59
                });
60
            });
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
61
        });
62
    }
63
64
    function getOrder(res, apiKey, orderId) {
65 7
        if (Number.isInteger(parseInt(orderId))) {
66 6
            db.get("SELECT " + dataFields +
67
                " FROM orders o INNER JOIN status s ON s.id = o.statusId" +
68
                " WHERE o.apiKey = ? AND orderId = ?",
69
            apiKey,
70
            orderId, (err, order) => {
71 6
                if (err) {
72
                    return res.status(500).json({
73
                        errors: {
74
                            status: 500,
75
                            source: "/order/" + orderId,
76
                            title: "Database error",
77
                            detail: err.message
78
                        }
79
                    });
80
                }
81
82 6
                if (order === undefined) {
83 1
                    return res.json({ data: {} });
84
                }
85
86 5
                order.order_items = [];
87 5
                db.each("SELECT " + orderItemsDataFields + " FROM order_items oi " +
88
                    " INNER JOIN products p ON oi.productId=p.productId" +
89
                    " AND oi.apiKey=p.apiKey" +
90
                    " WHERE oi.apiKey = ? AND oi.orderId = ?",
91
                apiKey,
92
                order.id, (err, orderItemRow) => {
93 2
                    if (err) {
94
                        return res.status(500).json({
95
                            errors: {
96
                                status: 500,
97
                                source: "/order/" + orderId + " order_items",
98
                                title: "Database error",
99
                                detail: err.message
100
                            }
101
                        });
102
                    }
103
104 2
                    order.order_items.push(orderItemRow);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
105
                }, function () {
106 5
                    res.json({ data: order });
107
                });
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
108
            });
109
        } else {
110 1
            res.status(400).json({
111
                errors: {
112
                    status: 400,
113
                    detail: "Required attribute order id " +
114
                        " is not an integer."
115
                }
116
            });
117
        }
118
    }
119
120
    function searchOrder(res, apiKey, query) {
121 2
        const searchQuery = "%" + query + "%";
122 2
        let orders = { data: []};
123
124 2
        db.all("SELECT " + dataFields +
125
            " FROM orders o INNER JOIN status s ON s.id = o.statusId" +
126
            " WHERE o.apiKey = ? AND" +
127
            "(customerName LIKE ? OR customerAddress LIKE ? OR customerZip LIKE ?" +
128
            " OR customerCity LIKE ? OR customerCountry LIKE ?)",
129
        apiKey,
130
        searchQuery,
131
        searchQuery,
132
        searchQuery,
133
        searchQuery,
134
        searchQuery, (err, orderRows) => {
135 2
            if (err) {
136
                return res.status(500).json({
137
                    errors: {
138
                        status: 500,
139
                        source: "/order/search/" + query,
140
                        title: "Database error",
141
                        detail: err.message
142
                    }
143
                });
144
            }
145
146 2
            if (orderRows.length === 0) {
147 1
                return res.json(orders);
148
            }
149
150 1 View Code Duplication
            orderRows.forEach(function(order) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
151 1
                db.all("SELECT " + orderItemsDataFields + " FROM order_items oi " +
152
                    " INNER JOIN products p ON oi.productId=p.productId" +
153
                    " AND oi.apiKey=p.apiKey WHERE oi.apiKey = ? AND oi.orderId = ?",
154
                apiKey,
155
                order.id, (err, orderItemRows) => {
156 2
                    if (err) {
157
                        return res.status(500).json({
158
                            errors: {
159
                                status: 500,
160
                                source: "/order/search/" + query + " order_items",
161
                                title: "Database error",
162
                                detail: err.message
163
                            }
164
                        });
165
                    }
166
167 1
                    order.order_items = orderItemRows;
168 1
                    orders.data.push(order);
169
170 2
                    if (orders.data.length === orderRows.length) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if orders.data.length === orderRows.length is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
171 1
                        res.json(orders);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
172
                    }
173
                });
174
            });
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
175
        });
176
    }
177
178
    function addOrder(res, body) {
179 6
        db.run("INSERT INTO orders (orderId, customerName, customerAddress, customerZip," +
180
            " customerCity, customerCountry, statusId, apiKey) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
181
        body.id,
182
        body.name,
183
        body.address,
184
        body.zip,
185
        body.city,
186
        body.country,
187
        body.status_id || 100,
188
        body.api_key, (err) => {
189 6
            if (err) {
190 3
                return res.status(500).json({
191
                    errors: {
192
                        status: 500,
193
                        source: "POST /order",
194
                        title: "Database error",
195
                        detail: err.message
196
                    }
197
                });
198
            } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
199 3
                res.status(201).json({ data: body });
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
200
            }
201
        });
202
    }
203
204
    function updateOrder(res, body) {
205 2
        if (Number.isInteger(parseInt(body.id))) {
206 1
            db.run("UPDATE orders SET customerName = ?, customerAddress = ?, customerZip = ?," +
207
                " customerCity = ?, customerCountry = ?, statusId = ?" +
208
                " WHERE apiKey = ? AND orderId = ?",
209
            body.name,
210
            body.address,
211
            body.zip,
212
            body.city,
213
            body.country,
214
            body.status_id || 100,
215
            body.api_key,
216
            body.id, (err) => {
217 2
                if (err) {
218
                    return res.status(500).json({
219
                        errors: {
220
                            status: 500,
221
                            source: "PUT /order",
222
                            title: "Database error",
223
                            detail: err.message
224
                        }
225
                    });
226
                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
227 1
                    res.status(204).send();
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
228
                }
229
            });
230
        } else {
231 1
            res.status(400).json({
232
                errors: {
233
                    status: 400,
234
                    detail: "Required attribute order id (id) " +
235
                        " was not included in the request."
236
                }
237
            });
238
        }
239
    }
240
241
    function deleteOrder(res, body) {
242 2
        if (Number.isInteger(parseInt(body.id))) {
243 1
            db.run("DELETE FROM orders WHERE apiKey = ? AND orderId = ?",
244
                body.api_key,
245
                body.id, (err) => {
246 2
                    if (err) {
247
                        return res.status(500).json({
248
                            errors: {
249
                                status: 500,
250
                                source: "DELETE /order",
251
                                title: "Database error",
252
                                detail: err.message
253
                            }
254
                        });
255
                    } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
256 1
                        db.run("DELETE FROM order_items WHERE apiKey = ? AND orderId = ?",
257
                            body.api_key,
258
                            body.id, (err) => {
259 2
                                if (err) {
260
                                    return res.status(500).json({
261
                                        errors: {
262
                                            status: 500,
263
                                            source: "DELETE /order order_items",
264
                                            title: "Database error",
265
                                            detail: err.message
266
                                        }
267
                                    });
268
                                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
269 1
                                    res.status(204).send();
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
270
                                }
271
                            });
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
272
                    }
273
                });
274
        } else {
275 1
            res.status(400).json({
276
                errors: {
277
                    status: 400,
278
                    detail: "Required attribute order id (id) " +
279
                        " was not included in the request."
280
                }
281
            });
282
        }
283
    }
284
285 1
    return {
286
        getAllOrders: getAllOrders,
287
        getOrder: getOrder,
288
        searchOrder: searchOrder,
289
        addOrder: addOrder,
290
        updateOrder: updateOrder,
291
        deleteOrder: deleteOrder,
292
    };
293
}());
294